use crate::src::src::trie::{
    trie_free, trie_insert, trie_insert_binary, trie_lookup, trie_lookup_binary, trie_new,
    trie_num_entries, trie_remove, trie_remove_binary,
};
use crate::src::struct_and_type::{size_t, Trie, TrieValue, UnitTestFunction};
use crate::src::test::alloc_testing::{
    alloc_test_free, alloc_test_get_allocated, alloc_test_malloc, alloc_test_set_limit,
};
use crate::src::test::framework::run_tests;

extern "C" {
    fn sprintf(_: *mut i8, _: *const i8, _: ...) -> i32;
    fn memset(_: *mut (), _: i32, _: u64) -> *mut ();
    fn strcmp(_: *const i8, _: *const i8) -> i32;
}
#[no_mangle]
pub static mut test_array_test_trie: [i32; 10000] = [0; 10000];
#[no_mangle]
pub static mut test_strings: [[i8; 10]; 10000] = [[0; 10]; 10000];
#[no_mangle]
pub static mut bin_key: [u8; 7] = [
    'a' as i32 as u8,
    'b' as i32 as u8,
    'c' as i32 as u8, 0 as u8, 1 as u8, 2 as u8,
    0xff as i32 as u8,
];
#[no_mangle]
pub static mut bin_key2: [u8; 8] = [
    'a' as i32 as u8,
    'b' as i32 as u8,
    'c' as i32 as u8, 0 as u8, 1 as u8, 2 as u8,
    0xff as i32 as u8, 0 as u8,
];
#[no_mangle]
pub static mut bin_key3: [u8; 3] = ['a' as i32 as u8, 'b' as i32 as u8, 'c' as i32 as u8];
#[no_mangle]
pub static mut bin_key4: [u8; 4] = [
    'z' as i32 as u8, 0 as u8,
    'z' as i32 as u8,
    'z' as i32 as u8,
];
#[no_mangle]
pub extern "C" fn generate_trie() -> *mut Trie {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut i: i32 = 0;
    let mut entries: u32 = 0;
    trie = trie_new();
    entries = 0 as u32;
    i = 0;
    while i < 10000 {
        (unsafe { test_array_test_trie[i as usize] = i });
        (unsafe {
            sprintf(
                (test_strings[i as usize]).as_mut_ptr(),
                b"%i\0" as *const u8 as *const i8,
                i,
            )
        });
        assert!(
            trie_insert(
                trie,
                unsafe { (test_strings[i as usize]).as_mut_ptr() },
                (unsafe { &mut *test_array_test_trie.as_mut_ptr().offset(i as isize) }) as *mut i32
                    as TrieValue,
            ) != 0
        );
        entries = entries.wrapping_add(1);
        entries;
        assert!(trie_num_entries(trie) == entries);
        i += 1;
        i;
    }
    return trie;
}
#[no_mangle]
pub extern "C" fn test_trie_new_free() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    trie = trie_new();
    assert!(!trie.is_null());
    trie_free(trie);
    trie = trie_new();
    assert!(
        trie_insert(
            trie,
            b"hello\0" as *const u8 as *const i8 as *mut i8,
            b"there\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(
        trie_insert(
            trie,
            b"hell\0" as *const u8 as *const i8 as *mut i8,
            b"testing\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(
        trie_insert(
            trie,
            b"testing\0" as *const u8 as *const i8 as *mut i8,
            b"testing\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(
        trie_insert(
            trie,
            b"\0" as *const u8 as *const i8 as *mut i8,
            b"asfasf\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    trie_free(trie);
    trie = trie_new();
    assert!(
        trie_insert(
            trie,
            b"hello\0" as *const u8 as *const i8 as *mut i8,
            b"there\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(trie_remove(trie, b"hello\0" as *const u8 as *const i8 as *mut i8,) != 0);
    trie_free(trie);
    alloc_test_set_limit(0 as i32);
    trie = trie_new();
    assert!(trie.is_null());
}
#[no_mangle]
pub extern "C" fn test_trie_insert() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut entries: u32 = 0;
    let mut allocated: size_t = 0;
    trie = generate_trie();
    entries = trie_num_entries(trie);
    assert!(
        trie_insert(
            trie,
            b"hello world\0" as *const u8 as *const i8 as *mut i8,
            core::ptr::null_mut(),
        ) == 0
    );
    assert!(trie_num_entries(trie) == entries);
    allocated = alloc_test_get_allocated();
    alloc_test_set_limit(0 as i32);
    assert!(
        trie_insert(
            trie,
            b"a\0" as *const u8 as *const i8 as *mut i8,
            b"test value\0" as *const u8 as *const i8 as TrieValue,
        ) == 0
    );
    assert!(trie_num_entries(trie) == entries);
    alloc_test_set_limit(5 as i32);
    assert!(
        trie_insert(
            trie,
            b"hello world\0" as *const u8 as *const i8 as *mut i8,
            b"test value\0" as *const u8 as *const i8 as TrieValue,
        ) == 0
    );
    assert!(alloc_test_get_allocated() == allocated);
    assert!(trie_num_entries(trie) == entries);
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_lookup() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut buf: [i8; 10] = [0; 10];
    let mut val: *mut i32 = 0 as *mut i32;
    let mut i: i32 = 0;
    trie = generate_trie();
    assert!((trie_lookup(
        trie,
        b"000000000000000\0" as *const u8 as *const i8 as *mut i8,
    ))
    .is_null());
    assert!((trie_lookup(trie, b"\0" as *const u8 as *const i8 as *mut i8,)).is_null());
    i = 0;
    while i < 10000 {
        (unsafe { sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const i8, i) });
        val = trie_lookup(trie, buf.as_mut_ptr()) as *mut i32;
        assert!((unsafe { *val }) == i);
        i += 1;
        i;
    }
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_remove() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut buf: [i8; 10] = [0; 10];
    let mut i: i32 = 0;
    let mut entries: u32 = 0;
    trie = generate_trie();
    assert!(
        trie_remove(
            trie,
            b"000000000000000\0" as *const u8 as *const i8 as *mut i8,
        ) == 0
    );
    assert!(trie_remove(trie, b"\0" as *const u8 as *const i8 as *mut i8) == 0);
    entries = trie_num_entries(trie);
    assert!(entries == 10000 as u32);
    i = 0;
    while i < 10000 {
        (unsafe { sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const i8, i) });
        assert!(trie_remove(trie, buf.as_mut_ptr()) != 0);
        entries = entries.wrapping_sub(1);
        entries;
        assert!(trie_num_entries(trie) == entries);
        i += 1;
        i;
    }
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_replace() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut val: *mut i32 = 0 as *mut i32;
    trie = generate_trie();
    val = alloc_test_malloc(::core::mem::size_of::<i32>() as u64) as *mut i32;
    (unsafe { *val = 999 });
    assert!(
        trie_insert(
            trie,
            b"999\0" as *const u8 as *const i8 as *mut i8,
            val as TrieValue,
        ) != 0
    );
    assert!(trie_num_entries(trie) == 10000 as u32);
    assert!(trie_lookup(trie, b"999\0" as *const u8 as *const i8 as *mut i8,) == val as TrieValue);
    alloc_test_free(val as *mut ());
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_insert_empty() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut buf: [i8; 10] = [0; 10];
    trie = trie_new();
    assert!(
        trie_insert(
            trie,
            b"\0" as *const u8 as *const i8 as *mut i8,
            buf.as_mut_ptr() as TrieValue,
        ) != 0
    );
    assert!(trie_num_entries(trie) != 0 as u32);
    assert!(
        trie_lookup(trie, b"\0" as *const u8 as *const i8 as *mut i8)
            == buf.as_mut_ptr() as TrieValue
    );
    assert!(trie_remove(trie, b"\0" as *const u8 as *const i8 as *mut i8) != 0);
    assert!(trie_num_entries(trie) == 0 as u32);
    trie_free(trie);
}
extern "C" fn test_trie_free_long() {
    let mut long_string: *mut i8 = 0 as *mut i8;
    let mut trie: *mut Trie = 0 as *mut Trie;
    long_string = alloc_test_malloc(4096 as i32 as size_t) as *mut i8;
    (unsafe {
        memset(
            long_string as *mut (),
            'A' as i32, 4096 as u64,
        )
    });
    (unsafe { *long_string.offset((4096 as i32 - 1) as isize) = '\0' as i32 as i8 });
    trie = trie_new();
    trie_insert(trie, long_string, long_string as TrieValue);
    trie_free(trie);
    alloc_test_free(long_string as *mut ());
}
extern "C" fn test_trie_negative_keys() {
    let mut my_key: [i8; 6] = [
        'a' as i32 as i8,
        'b' as i32 as i8,
        'c' as i32 as i8,
        -(50 as i32) as i8,
        -(20 as i32) as i8,
        '\0' as i32 as i8,
    ];
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut value: *mut () = core::ptr::null_mut();
    trie = trie_new();
    assert!(
        trie_insert(
            trie,
            my_key.as_mut_ptr(),
            b"hello world\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    value = trie_lookup(trie, my_key.as_mut_ptr());
    assert!(
        (unsafe {
            strcmp(
                value as *const i8,
                b"hello world\0" as *const u8 as *const i8,
            )
        }) == 0
    );
    assert!(trie_remove(trie, my_key.as_mut_ptr()) != 0);
    assert!(trie_remove(trie, my_key.as_mut_ptr()) == 0);
    assert!((trie_lookup(trie, my_key.as_mut_ptr())).is_null());
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn generate_binary_trie() -> *mut Trie {
    let mut trie: *mut Trie = 0 as *mut Trie;
    trie = trie_new();
    assert!(
        trie_insert_binary(
            trie,
            unsafe { bin_key2.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 8]>() as u64 as i32,
            b"goodbye world\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(
        trie_insert_binary(
            trie,
            unsafe { bin_key.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
            b"hello world\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    return trie;
}
#[no_mangle]
pub extern "C" fn test_trie_insert_binary() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut value: *mut i8 = 0 as *mut i8;
    trie = generate_binary_trie();
    assert!(
        trie_insert_binary(
            trie,
            unsafe { bin_key.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
            b"hi world\0" as *const u8 as *const i8 as TrieValue,
        ) != 0
    );
    assert!(
        trie_insert_binary(
            trie,
            unsafe { bin_key3.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 3]>() as u64 as i32,
            core::ptr::null_mut(),
        ) == 0
    );
    value = trie_lookup_binary(
        trie,
        unsafe { bin_key.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
    ) as *mut i8;
    assert!((unsafe { strcmp(value, b"hi world\0" as *const u8 as *const i8) }) == 0);
    value = trie_lookup_binary(
        trie,
        unsafe { bin_key2.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 8]>() as u64 as i32,
    ) as *mut i8;
    assert!((unsafe { strcmp(value, b"goodbye world\0" as *const u8 as *const i8) }) == 0);
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_insert_out_of_memory() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    trie = generate_binary_trie();
    alloc_test_set_limit(3 as i32);
    assert!(
        trie_insert_binary(
            trie,
            unsafe { bin_key4.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 4]>() as u64 as i32,
            b"test value\0" as *const u8 as *const i8 as TrieValue,
        ) == 0
    );
    assert!((trie_lookup_binary(
        trie,
        unsafe { bin_key4.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 4]>() as u64 as i32,
    ))
    .is_null());
    assert!(trie_num_entries(trie) == 2 as u32);
    trie_free(trie);
}
#[no_mangle]
pub extern "C" fn test_trie_remove_binary() {
    let mut trie: *mut Trie = 0 as *mut Trie;
    let mut value: *mut () = core::ptr::null_mut();
    trie = generate_binary_trie();
    value = trie_lookup_binary(
        trie,
        unsafe { bin_key3.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 3]>() as u64 as i32,
    );
    assert!(value.is_null());
    assert!(
        trie_remove_binary(
            trie,
            unsafe { bin_key3.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 3]>() as u64 as i32,
        ) == 0
    );
    assert!((trie_lookup_binary(
        trie,
        unsafe { bin_key4.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 4]>() as u64 as i32,
    ))
    .is_null());
    assert!(
        trie_remove_binary(
            trie,
            unsafe { bin_key4.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 4]>() as u64 as i32,
        ) == 0
    );
    assert!(
        trie_remove_binary(
            trie,
            unsafe { bin_key2.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 8]>() as u64 as i32,
        ) != 0
    );
    assert!((trie_lookup_binary(
        trie,
        unsafe { bin_key2.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 8]>() as u64 as i32,
    ))
    .is_null());
    assert!(!(trie_lookup_binary(
        trie,
        unsafe { bin_key.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
    ))
    .is_null());
    assert!(
        trie_remove_binary(
            trie,
            unsafe { bin_key.as_mut_ptr() },
            ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
        ) != 0
    );
    assert!((trie_lookup_binary(
        trie,
        unsafe { bin_key.as_mut_ptr() },
        ::core::mem::size_of::<[u8; 7]>() as u64 as i32,
    ))
    .is_null());
    trie_free(trie);
}
static mut tests_test_trie: [UnitTestFunction; 12] = {
    [
        Some(test_trie_new_free as unsafe extern "C" fn() -> ()),
        Some(test_trie_insert as unsafe extern "C" fn() -> ()),
        Some(test_trie_lookup as unsafe extern "C" fn() -> ()),
        Some(test_trie_remove as unsafe extern "C" fn() -> ()),
        Some(test_trie_replace as unsafe extern "C" fn() -> ()),
        Some(test_trie_insert_empty as unsafe extern "C" fn() -> ()),
        Some(test_trie_free_long as unsafe extern "C" fn() -> ()),
        Some(test_trie_negative_keys as unsafe extern "C" fn() -> ()),
        Some(test_trie_insert_binary as unsafe extern "C" fn() -> ()),
        Some(test_trie_insert_out_of_memory as unsafe extern "C" fn() -> ()),
        Some(test_trie_remove_binary as unsafe extern "C" fn() -> ()),
        None,
    ]
};
fn main_0_test_trie(mut _argc: i32, mut _argv: *mut *mut i8) -> i32 {
    run_tests(unsafe { tests_test_trie.as_mut_ptr() });
    return 0;
}
pub fn main_test_trie() {
    let mut args: Vec<*mut i8> = Vec::new();
    for arg in ::std::env::args() {
        args.push(
            (::std::ffi::CString::new(arg))
                .expect("Failed to convert argument into CString.")
                .into_raw(),
        );
    }
    args.push(::core::ptr::null_mut());
    {
        ::std::process::exit(main_0_test_trie(
            (args.len() - 1) as i32,
            args.as_mut_ptr() as *mut *mut i8,
        ) as i32)
    }
}
